/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.cratos.xxgram.platf.message;

import java.security.SecureRandom;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.persistence.Transient;

import org.redkale.convert.json.JsonConvert;
import org.redkale.service.RetResult;
import org.redkale.source.DataSource;
import org.redkale.source.FilterExpress;
import org.redkale.source.FilterNode;
import org.redkale.util.Comment;

import com.cratos.xxgram.platf.base.RetCodes;
import com.cratos.xxgram.platf.base.UserInfo;
import com.cratos.xxgram.platf.friend.FriendShip;
import com.cratos.xxgram.platf.group.UserGroup;
import com.cratos.xxgram.platf.user.UserDetail;
import com.cratos.xxgram.platf.util.ShuffleRandom;

/**
 * 消息回调处理
 *
 * @author SquRab
 */
public abstract class MessageHandler {

    @Comment("对象转换")
    public JsonConvert jsonConvert = JsonConvert.root();

    protected final Logger logger = Logger.getLogger(this.getClass().getSimpleName());

    protected final boolean finer = logger.isLoggable(Level.FINER);

    protected final boolean finest = logger.isLoggable(Level.FINEST);

    @Transient //随机源
    protected final SecureRandom idRandom = ShuffleRandom.createRandom();
     
    @Comment("消息回调")
    public CompletableFuture<MessageRecord> handler(MessageService messageService, MessageRecord record) {
        throw new UnsupportedOperationException(" Unsupported ......");
    }

    
    @Comment("消息校验")
    protected final CompletableFuture<RetResult> validateMessage(MessageService messageService, MessageRecord record) {
    	CompletableFuture<RetResult> feature = new CompletableFuture<RetResult>();
        // 统一解密消息
        String content = messageService.decodeContent(record).getContent();
        Class clazz = getContentClass();
        logger.finest("clazz xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx " + clazz + ", content =" + content);
        record.setContentObj(jsonConvert.convertFrom(clazz, content));
        logger.finest("clazz record eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee " + record + " obj ===" + record.getContentObj());
    	feature.complete(validate(messageService, record));
    	return feature;
    }
    
    @Comment("消息校验")
    protected RetResult validate(MessageService messageService, MessageRecord record) {
    	DataSource source = messageService.getSource();
        int messageKind = record.getMsgkind();
        short msgType = record.getMsgtype();
        // 如果是私聊消息需要查看是否为好友 todo 需要确认好友被拉黑是否能发消息
        if (messageKind == MessageRecord.MSG_KIND_PRIVATE) {
            UserDetail friendDetail = messageService.getSource().find(UserDetail.class, record.getTargetid());
            if (friendDetail == null) {
                return RetCodes.retResult(RetCodes.RET_USER_CANCEL);
            }
            boolean isFriend = source.exists(FriendShip.class, FilterNode.create("userid", FilterExpress.EQUAL, record.getFromid()).and("friendid", FilterExpress.EQUAL, record.getTargetid()));
            if (!isFriend) {
                return RetCodes.retResult(RetCodes.RET_FRIENDSHI_FRIENDINFO_NOTEXIT_FIRIND);
            }
            // 校验黑名单
	        FriendShip ship = source.find(FriendShip.class, FilterNode.create("friendid", FilterExpress.EQUAL, record.getFromid()).and("userid", FilterExpress.EQUAL, record.getTargetid()));
	        if (ship == null) return RetCodes.retResult(RetCodes.RET_FRIENDSHI_FRIENDINFO_NOTEXIT_FIRIND);
	        if (ship.getRelationship() == FriendShip.RELATION_SHIP_BLACKLIST) {
	           return RetCodes.retResult(RetCodes.RET_FRIENDSHI_BLACKLIST_FIRIND);
	        }
        }
        // 校验用户是否在群组中
        if (messageKind == MessageRecord.MSG_KIND_GROUP && record.getMsgtype() < 2000) {
            UserGroup userGroup = source.find(UserGroup.class, FilterNode.create("userid", FilterExpress.EQUAL, record.getFromid()).and("groupid", FilterExpress.EQUAL, record.getTargetid()));
            if (userGroup == null) {
                return RetCodes.retResult(RetCodes.RET_RONGCLOUD_USER_NOTIN_GROUP);
            }
            long setting = userGroup.getSyssetting();
            // 查看当前是否为全员禁言 第一位
            if ((setting & 1) == 1) {
                return RetCodes.retResult(RetCodes.RET_RONGCLOUD_SPEAKNOTALLOW_IN_GROUP);
            }
        }
        
        if (messageKind == MessageRecord.MSG_KIND_SYSTEM) {
        	// 添加好友方式验证
        	if (msgType == NotifyContent.OBJ_CONTRACT_NTF) {
                    int friendid = record.getTargetid();
                    UserInfo friendInfo = source.find(UserInfo.class, friendid);
                    if (friendInfo == null) return RetCodes.retResult(RetCodes.RET_USER_NOTEXIT_FIRIND);//用户不存在
                    long syssetting = friendInfo.getSyssetting(); //被添加用户配置信息
                    NotifyContent.ContactNotificationMessage reqMsg = jsonConvert.convertFrom(NotifyContent.ContactNotificationMessage.class, messageService.decodeContent(record).getContent());
                    short  invitetype = reqMsg.getInvitetype();
                    // 第14位表示 添加我的方式  手机号码
                    if ((syssetting & 8192) != 8192 && invitetype == FriendShip.REQ_BY_MOBILE) {
                        return RetCodes.retResult(RetCodes.RET_FRIENDSHI_BINDFRIENDSHIP_FAILED);
                    }

                    // 第15位表示 添加我的方式  ID添加
                    if ((syssetting & 16384) != 16384 && invitetype == FriendShip.REQ_BY_ID) {
                        return RetCodes.retResult(RetCodes.RET_FRIENDSHI_BINDFRIENDSHIP_FAILED);
                    }

                    // 第16位表示 添加我的方式  我的二维码
                    if ((syssetting & 32768) != 32768 && invitetype == FriendShip.REQ_BY_SCAN) {
                        return RetCodes.retResult(RetCodes.RET_FRIENDSHI_BINDFRIENDSHIP_FAILED);
                    }
        	}
        }
       
        return RetResult.success();
    }
    
    @Comment("消息发送")
    public CompletableFuture<Integer> sendMessage(MessageService messageService, MessageRecord record) {
        logger.finest("sendMessage  Class :" + this.getClass() + "send record =====>>>>>" + record);
        return messageService.sendMessage(record);
    }

    @Comment("消息发送")
    public void sendNotifyMessage(MessageService messageService, MessageRecord record, List<Integer> receivers) {
        logger.finest("sendNotifyMessage Class :" + this.getClass() + "send record =====>>>>>" + record);
        messageService.sendNotifyMessage(record, receivers);
    }
    
      @Comment("消息发送")
    public CompletableFuture<Integer>  sendNotifyMessageWithSave(MessageService messageService, MessageRecord record, Collection<Integer> receivers) {
       logger.finest("sendNotifyMessageWithSave Class :" + this.getClass() + "send record =====>>>>>" + record);
       return messageService.sendNotifyMessageWithSave(record, receivers);
    }
      
    @Comment("消息处理器")
    private static final HashMap<Short, MessageHandler> handlerMap = new HashMap<Short, MessageHandler>();

    static {
        handlerMap.put(BasicContent.FileMessage.TYPE, BasicContentHandler.FileMessageHandler.instance);
        handlerMap.put(BasicContent.SightMessage.TYPE, BasicContentHandler.SightMessageHandler.instance);
        handlerMap.put(BasicContent.TextMessage.TYPE, BasicContentHandler.TextMessageHandler.instance);
        handlerMap.put(BasicContent.LocationMessage.TYPE, BasicContentHandler.LocationMessageHandler.instance);
        handlerMap.put(BasicContent.RichContentMessage.TYPE, BasicContentHandler.RichContentMessageHandler.instance);
        handlerMap.put(BasicContent.GroupContentMessage.TYPE, BasicContentHandler.GroupContentMessageHandler.instance);
        handlerMap.put(BasicContent.ShareFileMessage.TYPE, BasicContentHandler.ShareFileMessageHandler.instance);// 分享文件
        handlerMap.put(BasicContent.AudioMessage.TYPE, BasicContentHandler.AudioMessageHandler.instance);// 音频消息文件
        handlerMap.put(BasicContent.ImageMessage.TYPE, BasicContentHandler.ImageMessageHandler.instance);// 图片消息消息文件
        handlerMap.put(BasicContent.TipMessage.TYPE, BasicContentHandler.TipMessageHandler.instance);// tip提示消息
        handlerMap.put(BasicContent.ShareCardNotify.TYPE, BasicContentHandler.ShareCardHandler.instance);//分享名片
        handlerMap.put(BasicContent.RongCloudVoiceMessage.TYPE, BasicContentHandler.RongCloudVoiceHandler.instance);//融云语音消息
        handlerMap.put(BasicContent.MerageForwordMessage.TYPE, BasicContentHandler.MeargeFrowordMessageHandler.instance);//消息合并转发
        
        // 
        //* **************************通知消息NotifyContent***************************************
        handlerMap.put(NotifyContent.InformationNotificationMessage.TYPE, NotifyHandler.InformationNotificationHandler.instance);
        handlerMap.put(NotifyContent.ContactNotificationMessage.TYPE, NotifyHandler.ContactNotificationHanler.instance);
        // 已读未读回执
        handlerMap.put(NotifyContent.ReadReceiptMessage.TYPE, NotifyHandler.ReadReceiptHandler.instance);
        //***************************** 群通知消息 **********************************************
        handlerMap.put(NotifyContent.CreateGroupNotify.TYPE, NotifyHandler.CreateGroupHandler.instance);
        handlerMap.put(NotifyContent.UpdateGroupNotify.TYPE, NotifyHandler.UpdateGroupHandler.instance);
        handlerMap.put(NotifyContent.AddMemberToGroupNotify.TYPE, NotifyHandler.AddMemberToGroupHandler.instance);
        handlerMap.put(NotifyContent.KickedGroupNotify.TYPE, NotifyHandler.KickedGroupHandler.instance);
        handlerMap.put(NotifyContent.QuitGroupNotify.TYPE, NotifyHandler.QuitGroupHandler.instance);
        handlerMap.put(NotifyContent.DissMissGroupNotify.TYPE, NotifyHandler.DissMissGroupHandler.instance);
        handlerMap.put(NotifyContent.UpdateUserGroupNameNotify.TYPE, NotifyHandler.UpdateUserGroupNameHanler.instance);
       
        handlerMap.put(NotifyContent.StealthWithFriendsNotify.TYPE, NotifyHandler.StealthWithFriendsHandler.instance);// 对好友进行隐身
        handlerMap.put(NotifyContent.UserOnlineStatusNotify.TYPE, NotifyHandler.UserOnlineStatusHandler.instance);// 用户在线状态通知
        handlerMap.put(NotifyContent.ReCallNotify.TYPE, NotifyHandler.ReCallNotifyHandler.instance);//撤回消息
        handlerMap.put(NotifyContent.ReCallAllNotify.TYPE, NotifyHandler.ReCallAllNotifyHandler.instance);//撤回全部消息
        handlerMap.put(NotifyContent.OnlineUserListNotify.TYPE, NotifyHandler.OnlineUserListHandler.instance);//在线好友列表  群在线好友列表
        handlerMap.put(NotifyContent.ForBiddenWordNotify.TYPE, NotifyHandler.ForBiddenWordHandler.instance);//禁言
        handlerMap.put(NotifyContent.LogOutH5Notify.TYPE, NotifyHandler.LogOutH5Handler.instance);//登出H5客户端
        handlerMap.put(NotifyContent.InputReadStateNotify.TYPE, NotifyHandler.InputReadStateHandler.instance);//输入或阅读状态
        handlerMap.put(NotifyContent.DisableH5Status.TYPE, NotifyHandler.DisableH5StatusHandler.instance);//APP 显示 登出H5状态
        handlerMap.put(NotifyContent.GroupReadReceiptNotify.TYPE, NotifyHandler.GroupReadReceiptNotifyHandler.instance);//群消息一度回执
        handlerMap.put(NotifyContent.GroupUpdateTypeNotify.TYPE, NotifyHandler.GroupUpdateTypeNotifyHandler.instance);//群消类型修改
        //GroupUpdateTypeNotifyHandler
    }
    
    @Comment("获取当前对象内容类型")
    protected abstract Class getContentClass();

    public static final MessageHandler fetchHandler(short msgType) {
        if (!handlerMap.containsKey(msgType)) {
            throw new UnsupportedOperationException("unsupport msgType === > " + msgType);
        }
        return handlerMap.get(msgType);
    }
}
